package de.baumann.browser.web;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.net.MailTo;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.View;

import com.orhanobut.logger.Logger;
import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient;
import com.tencent.smtt.sdk.CookieSyncManager;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;

import java.net.URISyntaxException;
import java.util.HashMap;

import de.baumann.browser.R;
import de.baumann.browser.browser.OdinClickHandler;
import de.baumann.browser.browser.OdinDownloadListener;
import de.baumann.browser.browser.OdinGestureListener;
import de.baumann.browser.browser.OdinWebChromeClient;
import de.baumann.browser.browser.OdinWebViewClient;
import de.baumann.browser.units.BrowserUnit;
import de.baumann.browser.units.IntentUnit;

public class OdinWebView extends WebView {

    private OnScrollChangeListener onScrollChangeListener;

    public OdinWebView(Context context) {
        this(context, null);
    }

    public OdinWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        this.webViewClient = new OdinWebViewClient(this);
        this.webChromeClient = new OdinWebChromeClient(this);
        this.downloadListener = new OdinDownloadListener(this.context);
        this.clickHandler = new OdinClickHandler(this);
        this.gestureDetector = new GestureDetector(context, new OdinGestureListener(this));
        this.foreground = true;
        getView().setClickable(true);
        initWebView();
        initWebSettings();
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (onScrollChangeListener != null) {
            onScrollChangeListener.onScrollChange(t, oldl);
        }
    }

    public void setOnScrollChangeListener(OnScrollChangeListener onScrollChangeListener) {
        this.onScrollChangeListener = onScrollChangeListener;
    }

    public interface OnScrollChangeListener {
        /**
         * Called when the scroll position of a view changes.
         *
         * @param scrollY    Current vertical scroll origin.
         * @param oldScrollY Previous vertical scroll origin.
         */
        void onScrollChange(int scrollY, int oldScrollY);
    }

    private Context context;

    private OdinWebViewClient webViewClient;
    private OdinWebChromeClient webChromeClient;
    private OdinDownloadListener downloadListener;
    private OdinClickHandler clickHandler;
    private GestureDetector gestureDetector;

    private SharedPreferences sp;

    private boolean foreground;

    public boolean isForeground() {
        return foreground;
    }

    private WebUiController uiController;

    public void setUiController(WebUiController uiController) {
        this.uiController = uiController;
    }

    public WebUiController getUiController() {
        return uiController;
    }


    @SuppressLint("ClickableViewAccessibility")
    private synchronized void initWebView() {
        setWebContentsDebuggingEnabled(true);
        setDrawingCacheEnabled(true);
        setWebViewClient(webViewClient);
        setWebChromeClient(webChromeClient);
        setDownloadListener(downloadListener);
        setOnTouchListener((view, motionEvent) -> {
            gestureDetector.onTouchEvent(motionEvent);
            return false;
        });

        CookieSyncManager.createInstance(context);
        CookieSyncManager.getInstance().sync();
    }

    @SuppressLint("SetJavaScriptEnabled")
    private synchronized void initWebSettings() {
        WebSettings webSetting = this.getSettings();
        webSetting.setJavaScriptEnabled(true);
        webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
        webSetting.setAllowFileAccess(true);
        webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSetting.setSupportZoom(true);
        webSetting.setBuiltInZoomControls(true);
        webSetting.setUseWideViewPort(true);
        webSetting.setSupportMultipleWindows(true);
        webSetting.setAppCacheEnabled(true);
        webSetting.setDomStorageEnabled(true);
        webSetting.setGeolocationEnabled(true);
        webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
        webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
        webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);
        webSetting.setTextZoom(100);
    }

    @Override
    public synchronized void loadUrl(String url) {

        if (TextUtils.isEmpty(url)) {
//            OdinToast.show(context, R.string.toast_load_error);
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
            final int i = sp.getInt(context.getString(R.string.sp_search_engine), 0);
            switch (i) {
                case 0:
                    url = BrowserUnit.BAIDU;
                    break;
                case 1:
                    url = BrowserUnit.BING;
                    break;
                case 2:
                    url = BrowserUnit.GOOGLE;
                    break;
                default:
            }
        }

        if (!url.contains("://")) {
            url = BrowserUnit.queryWrapper(context, url.trim());
        }

        if (url.startsWith(BrowserUnit.URL_SCHEME_MAIL_TO)) {
            Intent intent = IntentUnit.getEmailIntent(MailTo.parse(url));
            context.startActivity(intent);
            reload();
            return;

        } else if (url.startsWith(BrowserUnit.URL_SCHEME_INTENT)) {
            Intent intent;
            try {
                intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
                context.startActivity(intent);
            } catch (URISyntaxException u) {
                Logger.w("Error parsing URL");
            }
            return;
        }

        HashMap<String, String> extraHeaders = new HashMap<>(16);
        extraHeaders.put("DNT", "1");
        super.loadUrl(url, extraHeaders);
    }


    public synchronized void onPageStart(WebView webView, Bitmap favicon) {
        if (foreground && uiController != null) {
            uiController.onPageStarted(webView, favicon);
        }
    }

    public synchronized void onPageFinished(String title, String url) {
        if (foreground  && uiController != null) {
            uiController.onPageFinished(title, url);
        }
    }

    public synchronized void onProgressChanged(int progress) {
        if (foreground  && uiController != null) {
            uiController.onProgressChanged(progress);
        }
    }


    public synchronized void onReceivedTitle(String title, String url) {
        if (foreground  && uiController != null) {
            uiController.onReceivedTitle(TextUtils.isEmpty(title) ? url : title);
        }
    }

    public synchronized void showCustomView(View view, IX5WebChromeClient.CustomViewCallback callback) {
        if (foreground  && uiController != null) {
            uiController.showCustomView(view, callback);
        }
    }

    public synchronized void hideCustomView() {
        if (foreground  && uiController != null) {
            uiController.hideCustomView();
        }
    }


    @Override
    public synchronized void destroy() {
        stopLoading();
        clearHistory();
//        setVisibility(GONE);
        removeAllViews();
        destroyDrawingCache();
        super.destroy();
    }


    public boolean isLoadFinish() {
        return getProgress() >= BrowserUnit.PROGRESS_MAX;
    }

    public void onLongPress() {
        Message click = clickHandler.obtainMessage();
        if (click != null) {
            click.setTarget(clickHandler);
        }
        requestFocusNodeHref(click);
    }

    private boolean prepareRecord() {
        String title = getTitle();
        String url = getUrl();

        return !(title == null
                || title.isEmpty()
                || url == null
                || url.isEmpty()
                || url.startsWith(BrowserUnit.URL_SCHEME_ABOUT)
                || url.startsWith(BrowserUnit.URL_SCHEME_MAIL_TO)
                || url.startsWith(BrowserUnit.URL_SCHEME_INTENT));
    }
}
